import { reactive, watch, nextTick } from 'vue'
import { merge, throttle } from 'lodash'
import { clearParams } from './../utils.js'
import { ElMessage } from 'element-plus'

export default class FormEntity {
  constructor({ formData = {}, rules = {}, formConfig = {}, formRef, emit } = {}) {
    this.emit = emit
    this.data = reactive({
      initDataFlag: false, // 数据初始化是否完成
      formData, // 数据
      formRules: rules, // 数据校验
      formRef,
      formConfig: merge({
        mainKey: 'id', // 默认主键名称
        submitLoading: false, // 表单提交控制
        isLoading: false, // 表单获取数据中
        msg: '', // 提交后的提示语
        paramConfig: { // 提交参数数据根据这个对象配置进行区分的参数类型 { params: [], path: [], body: [] }
          params: [],
          path: [],
          body: []
        },
        getApi: null, // 获取表单数据接口
        draftApi: null, // 草稿表单数据接口
        editApi: null, // 编辑表单数据接口
        addApi: null, // 添加表单数据接口
        customGetInfo: null, // 自定义数据初始化方法 Function 示例 (params) => {}
        getDataBeforeFormat: null, // 数据设置前的处理 返回值必须包含result对象用于设置初始值 Function 示例 (d, p) => { ... }
        getDataAfter: null, // 数据设置后的处理 Function 示例 (d, p) => { ... }
        putDataClearKeys: [], // 数据保存前的数据处理 需要清理的 formData k
        putDataBeforeFormat: null, // 数据保存前的数据按数据key处理 Function 示例 (k,v) => v
        putDataBeforeFormatByFull: null, // 数据保存前的数据按整个Data处理,返回处理后的Data Function 示例 (d) => {}
        putDataBefore: null, // 数据保存前的回调方法,返回 false 可终止提交。 支持返回 Promise Function 示例 (d) => {}
        putDataAfter: null, // 数据保存后的回调方法 Function 示例 () => {}
        customSubmit: null // 自定义数据保存方法 Function 示例 (formData) => {}
      }, formConfig)
    })
  }

  bindFormInfo(params) {
    const formConfig = this.data.formConfig
    this.data.initDataFlag = true
    formConfig.isLoading = true
    if (formConfig.getApi && !formConfig.customGetInfo) {
      console.log('params', params)
      formConfig.getApi({ params }).then((res) => {
        formConfig && formConfig.getDataBeforeFormat && formConfig.getDataBeforeFormat(res, params)
        // 设置信息
        let { result, data } = res
        // 兼容处理
        if (!result) {
          result = data
        }
        if (result) {
          for (const key in this.data.formData) {
            if (result && Object.hasOwnProperty.call(result, key)) { // 设置信息
              this.data.formData[key] = result[key]
            }
          }
        }
        formConfig && formConfig.getDataAfter && formConfig.getDataAfter(res, params)
        this.bindClearValidate()
        this.data.initDataFlag = false
        formConfig.isLoading = false
      }).catch((e) => {
        console.log(e)
      })
    } else {
      formConfig.customGetInfo && formConfig.customGetInfo(params)
    }
  }
  setDefault(t) {
    for (const key in t) {
      if (Object.hasOwnProperty.call(this.data.formData, key)) {
        this.data.formData[key] = t[key]
      }
    }
  }
  getFormData() {
    const formConfig = this.data.formConfig
    const paramConfig = formConfig.paramConfig
    let formData = clearParams(this.data.formData, formConfig && formConfig.putDataClearKeys && formConfig.putDataClearKeys, formConfig && formConfig.putDataBeforeFormat)
    formConfig && formConfig.putDataBeforeFormatByFull && (formData = formConfig.putDataBeforeFormatByFull(formData))
    // 使用reduce简化分类逻辑
    const classifiedData = Object.keys(formData).reduce((acc, key) => {
      if (paramConfig?.params.includes(key)) {
        acc.params = acc.params || {};
        acc.params[key] = formData[key];
      } else if (paramConfig?.path.includes(key)) {
        acc.path = acc.path || {};
        acc.path[key] = formData[key];
      } else if (paramConfig?.body.includes(key)) {
        acc.body = acc.body || {};
        acc.body[key] = formData[key];
      }
      return acc;
    }, {})
    // 如果classifiedData有内容，则返回它；否则返回原始formData
    return Object.keys(classifiedData).length ? classifiedData : formData
  }
  // 保存草稿
  handleFormSaveDraft(callback) {
    if (!this.throttleFormSaveDraft) {
      this.throttleFormSaveDraft = throttle(() => {
        const formConfig = this.data.formConfig
        const data = this.getFormData()
        const req = formConfig.draftApi ? formConfig.draftApi : data[formConfig.mainKey] ? formConfig.editApi : formConfig.addApi
        typeof callback !== 'function' && (callback = '')
        req && !formConfig.customSubmit ? this.bindSaveData(req, data, 0, callback) : formConfig.customSubmit(data, callback)

      }, 1000)
    }
    this.throttleFormSaveDraft()
  }
  // 保存按钮绑定事件方法
  handleFormSave(callback) {
    if (!this.throttleFormSave) {
      this.throttleFormSave = throttle(() => {
        typeof callback !== 'function' && (callback = '')
        this.data.formRef.validate((v) => {
          if (v) {
            const formConfig = this.data.formConfig
            const data = this.getFormData()
            const req = data[formConfig.mainKey] ? formConfig.editApi : formConfig.addApi
            if (req && !formConfig.customSubmit) {
              const putDataBefore = formConfig.putDataBefore
              if (putDataBefore) {
                var response = putDataBefore(data)

                if (!response) {
                  callback && callback()
                  return
                }
                if (response instanceof Promise) {
                  response.then((e) => {
                    e ? this.bindSaveData(req, data, 1, callback) : Promise.reject(new Error('这个是错误的啊'))
                  }).catch(() => { callback && callback() })
                  return
                }
              }
              this.bindSaveData(req, data, 1, callback)
            } else {
              formConfig.customSubmit && formConfig.customSubmit(data, callback)
            }
          } else {
            callback && callback()
            ElMessage({
              message: '请检查表单项是否填写正确！',
              type: 'error',
              duration: 5 * 1000,
              customClass: 'full-message',
              onClose: () => { }
            })
          }
        })
      }, 1000)
    }
    this.throttleFormSave()
  }
  bindSaveData(req, data, reset, callback) {
    const formConfig = this.data.formConfig
    formConfig.submitLoading = true
    this.emit('save', true)
    req(data).then((d) => {
      console.log(d)
      const result = d.result || d.data || data[formConfig.mainKey] || ''
      this.data.formData[formConfig.mainKey] = result
      result && (data[formConfig.mainKey] = result)
      if (callback) {
        callback(d, data)
      } else {
        ElMessage({
          message: formConfig.msg || '保存成功',
          type: 'success',
          duration: 5 * 1000,
          customClass: 'full-message',
          onClose: () => { }
        })
        if (reset) {
          this.emit('change', true)
          this.handleFormReset()
        } else {
          // 用于保证草稿保存使列表更新
          this.emit('change', false)
        }
        this.emit('save', false)
      }
    }).catch((error) => {
      formConfig.submitLoading = false
      this.emit('save', false)
      callback && callback()
      console.log(error)
    })
  }
  // 重置清除按钮绑定方法
  handleFormReset() {
    const formConfig = this.data.formConfig
    formConfig.submitLoading = false
    formConfig.putDataAfter && formConfig.putDataAfter()
    nextTick(() => {
      this.resetFields()
    })
  }
  resetFields(fields) {
    if (this.data.formRef) {
      try {
        this.data.formRef.resetFields()
      } catch (error) {
        // console.log(error)
      }
      this.bindClearValidate(fields)
    }
  }
  bindClearValidate(fields) {
    nextTick(() => {
      if (this.data.formRef) {
        fields ? this.data.formRef.clearValidate(fields) : this.data.formRef.clearValidate()
      }
    })
  }
}